package com.forsythia.sns;

import java.net.InetAddress;
import java.security.SecureRandom;
import java.util.UUID;

import org.apache.log4j.Logger;


/**
 * Generate a unique identifier.
 */
public class SequenceUUID
{
  private static SequenceUUID oInstance = null;

  private static String midValue = null;
  
  private static Logger log = Logger.getLogger(SequenceUUID.class);
  
  public static synchronized SequenceUUID getInstance()
  {
    if (oInstance == null)
    {
      oInstance = new SequenceUUID();
    }
    return oInstance;
  }

  /**
   * Generate a univeral unique identifier
   * 
   * @return universal unique identifier
   */
  public String getUUID()
  {
    long timeNow = System.currentTimeMillis();
    int timeLow = (int) timeNow & 0xFFFFFFFF;

    if (midValue == null)
    {
      try
      {
        InetAddress inet = InetAddress.getLocalHost();
        byte[] bytes = inet.getAddress();
        String hexInetAddress = hexFormat(getInt(bytes), 8);
        String thisHashCode = hexFormat(System.identityHashCode(this), 8);
        midValue = hexInetAddress + thisHashCode;
      }
      catch (Exception e)
      {
    	  log.error(e.getMessage(),e);
      }
    }

    SecureRandom oRandom = new SecureRandom();
    int node = oRandom.nextInt();

    return (hexFormat(timeLow, 8) + midValue + hexFormat(node, 8));
  }

  /**
   * Returns an integer based on a byte array
   * 
   * @param bytes
   * @return
   */
  private static int getInt(byte[] bytes)
  {
    int i = 0;
    int j = 24;

    for (int k = 0; j >= 0; k++)
    {
      int l = bytes[k] & 0xff;
      i += (l << j);
      j -= 8;
    }

    return i;
  }

  /**
   * Returns the string representation of an integer with the necessary padding
   * 
   * @param i
   * @param j
   * @return
   */
  private static String hexFormat(int i, int j)
  {
    String s = Integer.toHexString(i);

    return padHex(s, j) + s;
  }

  /**
   * Pads a string with the required number of zeroes
   * 
   * @param s
   * @param i
   * @return
   */
  private static String padHex(String s, int i)
  {
    StringBuffer tmpBuffer = new StringBuffer();

    if (s.length() < i)
    {
      for (int j = 0; j < (i - s.length()); j++)
      {
        tmpBuffer.append('0');
      }
    }

    return tmpBuffer.toString();
  }
  
  public static void main(String[] args){
	  System.out.println(SequenceUUID.getInstance().getUUID());
	  
	  System.out.println(UUID.randomUUID());
  }
}
